
#include <stdio.h>
#include <memory.h>

#include "tools.h"
#include "uints_math.h"


void PrintHex(const char* head, const uint8_t* m, uint32_t len) {
    printf("%s:", head);
    for (uint32_t i=0; i<len; ++i) {
        printf("%02x ", m[i]);
    }
    printf("\n");
}



int UInts_Print(uint32_t *a, size_t size) {
	for (size_t i=0; i<size; ++i) {
		printf("%08X ", a[i]);
	}
	printf("\n");
}

static bool Test_Add() {
	bool r = true;

	{ // 普通加法
		uint32_t a[3] = {1,1,1};
		uint32_t b[3] = {2,2,2};
		uint32_t c[3];
		const uint32_t expect[3] = {3, 3, 3} ;
		
		bool rz = UInts_Add(a, 3, b, 3, c, 3);
		r = rz && UInts_Compare(c, 3, expect, 3) == 0 && r;
	}

	{	// 进位
		uint32_t a[3] = {0x70102301, 0xFFFFFFFF,0xEEEEEEEE};
		uint32_t b[3] = {0xE3129822, 0, 0x22222222};
		uint32_t c[4];
		const uint32_t expect[4] = {1, 0x5322bb24, 0, 0x11111110} ;
		
		bool rz = UInts_Add(a, 3, b, 3, c, 4);
		r = rz && UInts_Compare(c, 4, expect, 4) == 0 && r;
	}

	{	// 溢出
		uint32_t a[3] = {0x0000FFFF, 0xFFFFFFFF,0xEEEEEEEE};
		uint32_t b[3] = {0xFFFF0000, 0, 0x22222222};
		uint32_t c[3];
		const uint32_t expect[3] = {0, 0, 0x11111110} ;
		
		bool rz = UInts_Add(a, 3, b, 3, c, 3);
		r = !rz && UInts_Compare(c, 3, expect, 3) == 0 && r;
	}

	{	// 无溢出
		uint32_t a[3] = {0x0000FFFF, 0xFFFFFFFF,0xEEEEEEEE};
		uint32_t b[3] = {0xFFFF0000, 0, 0x22222222};
		uint32_t c[3];
		const uint32_t expect[3] = {0, 0, 0x11111110} ;
		
		bool rz = UInts_Add(a, 3, b, 3, c, 3);
		r = !rz && UInts_Compare(c, 3, expect, 3) == 0 && r;
	}
	return r;
}

/*
static bool Test_Sub() {
	
	bool r = true;

	{ // 普通减法
		uint32_t a[3] = {3,3,3};
		uint32_t b[3] = {2,2,2};
		uint32_t c[3];
		const uint32_t expect[3] = {1, 1, 1} ;
		
		bool rz = UInts_Sub(a, b, c, 3);
		r = !rz && UInts_Compare(c, expect, 3) == 0 && r;
	}

	{	// 借位
		uint32_t a[3] = {2, 0, 0};
		uint32_t b[3] = {1, 0, 0x22222222};
		uint32_t c[3];
		const uint32_t expect[3] = {0, 0xFFFFFFFF, 0xDDDDDDDE} ;
		
		bool rz = UInts_Sub(a, b, c, 3);
		r = !rz && UInts_Compare(c, expect, 3) == 0 && r;
	}

	{	// 溢出
		uint32_t a[3] = {0xF0001, 0, 0};
		uint32_t b[3] = {0xFFFF0000, 0, 2};
		uint32_t c[3];
		const uint32_t expect[3] = {0x00100000, 0xFFFFFFFF, 0xFFFFFFFE} ;
		
		bool rz = UInts_Sub(a, b, c, 3);
		r = rz && UInts_Compare(c, expect, 3) == 0 && r;
	}
	return r;
}

static bool Test_Mul() {
	bool r = true;

	{ // 没有高位
		uint32_t a[3] = {3,3,3};
		uint32_t b[3] = {0,0,2};
		uint32_t c[3];
		uint32_t d[3];
		const uint32_t expectc[3] = {6, 6, 6} ;
		const uint32_t expectd[3] = {0, 0, 0} ;
		
		bool rz = UInts_Mul(a, b, c, d, 3);
		r = !rz && UInts_Compare(c, expectc, 3) == 0 && 
			 UInts_Compare(d, expectd, 3) == 0 && r;
	}

	{ // 有高位
		uint32_t a[3] = {0x12345678, 0x22345678, 0x32345678};
		uint32_t b[3] = {0xFEDCBA98, 0xEEDCBA98, 0xDEDCBA98};
		uint32_t c[3];
		uint32_t d[3];
		const uint32_t expectc[3] = {0xebb2689a, 0x95c1bb0e, 0x35068740} ;
		const uint32_t expectd[3] = {0x121fa00a, 0x68104d96, 0xcbcb8164} ;
		
		bool rz = UInts_Mul(a, b, c, d, 3);
		r = rz && UInts_Compare(c, expectc, 3) == 0 && 
			 UInts_Compare(d, expectd, 3) == 0 && r;
	}

	{ // 取低位
		uint32_t a[3] = {0, 0x5678, 0xE3565678};
		uint32_t b[3] = {0, 0x20000004, 0xFEDCBA98};
		uint32_t c[3];
		const uint32_t expectc[3] = {0x1c6c7ac9, 0x0dd38ed1, 0x15368740} ;
		
		bool rz = UInts_Mul(a, b, c, NULL, 3);
		r = rz && UInts_Compare(c, expectc, 3) == 0 && r;
	}

	{ // 取高位
		uint32_t a[3] = {1, 0xF0D01234, 0x1234};
		uint32_t b[3] = {0, 0xFEDC, 0};
		uint32_t d[3];
		const uint32_t expectd[3] = {0, 0, 0x1ee99 };

		bool rz = UInts_Mul(a, b, NULL, d, 3);
		r = rz && UInts_Compare(d, expectd, 3) == 0 && r;
	}

	return r;
}
*/
static bool Test_Div() {

	bool r = true;

	{ // 没有余数
		uint32_t a[3] = {69,23,46};
		uint32_t b[3] = {0,0,23};
		uint32_t c[3];
		uint32_t d[3];
		const uint32_t expectc[3] = {3, 1, 2} ;
		const uint32_t expectd[3] = {0, 0, 0} ;
		
		UInts_Div(a, 3, b, 3, c, 3, d, 3);
		r = UInts_Compare(c, 3, expectc, 3) == 0 && 
			 UInts_Compare(d, 3, expectd, 3) == 0 && r;
	}

	{ // 有余数
		uint32_t a[3] = {0xFEDCBA98, 0xEEDCBA98, 0xDEDCBA98};
		uint32_t b[3] = {0x12345678, 0x22345678, 0x32345678};
		uint32_t c[3];
		uint32_t d[3];
		const uint32_t expectc[3] = {0, 0, 0xE} ;
		const uint32_t expectd[3] = {0x7, 0x10000006, 0x20000008};

		UInts_Div(a, 3, b, 3, c, 3, d, 3);
		r = UInts_Compare(c, 3, expectc, 3) == 0 && 
			 UInts_Compare(d, 3, expectd, 3) == 0 && r;
	}

	{ // 取商
		uint32_t a[3] = {0x12345600, 0x02345670, 0x00345678};
		uint32_t b[3] = {0, 0, 0x97714};
		uint32_t c[3];
		const uint32_t expectc[3] = {0x1ec, 0x5e31b9e1, 0x2128d36a};

		UInts_Div(a, 3, b, 3, c, 3, NULL, 3);
		r = UInts_Compare(c, 3, expectc, 3) == 0 && r;
	}


	{ // 取余数
		uint32_t a[3] = {0xFEDC, 0xCBA9, 0xDEDCBA98};
		uint32_t b[3] = {0, 0x70E000, 0x32345678};
		uint32_t d[3];
		const uint32_t expectd[3] = {0, 0x29907e, 0xb71ff0e0};

		UInts_Div(a, 3, b, 3, NULL, 3, d, 3);
		r = UInts_Compare(d, 3, expectd, 3) == 0 && r;
	}
	return r;
}


static bool Test_BitAdd() {
	bool r = true;

	{	
		uint32_t a[3] = {0xcdcdcdcd, 0x45454545, 0xb1b1b1b1};
		uint32_t b[3] = {0xe1e1e1e1, 0x43434343, 0x78787878};
		uint32_t c[3];
		const uint32_t expectc[3] = {0x2c2c2c2c, 0x06060606, 0xc9c9c9c9};

		bool rz = UInts_BitAdd(a, 3, b, 3, c, 3);
		r = rz && UInts_Compare(c, 3, expectc, 3) == 0 && r;

		rz = UInts_BitAdd(a, 3, b, 3, c, 2);
		r = !rz && UInts_Compare(c, 2, expectc+1, 2) == 0 && r;
	}

	{
		uint32_t a[3] = {0xcdcdcdcd, 0x45454545, 0xb1b1b1b1};
		uint32_t b[3] = {0xcdcdcdcd, 0x43434343, 0x78787878};
		uint32_t c[2];
		const uint32_t expectc[2] = {0x06060606, 0xc9c9c9c9};

		bool rz = UInts_BitAdd(a, 3, b, 3, c, 2);
		r = rz && UInts_Compare(c, 2, expectc, 2) == 0 && r;
	}
	return r;
}

static bool Test_BitMul() {
	bool r = true;

	return r;
}

bool SM_Test_UInts() {
	bool r = true;

	r = SM_TEST(Test_Add()) && r;
//	r = SM_TEST(Test_Sub()) && r;
//	r = SM_TEST(Test_Mul()) && r;
	r = SM_TEST(Test_Div()) && r; 

	r = SM_TEST(Test_BitAdd()) && r;
	r = SM_TEST(Test_BitMul()) && r;

	return r;
}
